// 工具函数库(https://www.html.cn/doc/lodash/)x
import {
    isEmpty as isEmptyFunc,
    isNaN as isNaNFunc,
    isNumber as isNumberFunc,
    isUndefined as isUndefinedFunc,
    clone as cloneFunc,
    cloneDeep as cloneDeepFunc
} from 'lodash';
// 时间库(https://github.com/iamkun/dayjs)
import dayjs from 'dayjs';
import storage from './storage';

export const isNaN = isNaNFunc;
export const isNumber = isNumberFunc;
export const isUndefined = isUndefinedFunc;
export const isNotUndefined = args => !isUndefinedFunc(args);
export const clone = cloneFunc;
export const cloneDeep = cloneDeepFunc;
export const isObject = obj => Object.prototype.toString.call(obj) === '[object Object]';

/**
 * @description: 将对象重新封装成{value:'',label:''}型对象,value 原对象属性值为label
 * @param {常量的名称} obj
 * @param {value值是否是number类型} isNumKey
 * @return: Array
 */
export const packSelectObjUtil = function (obj, isNumKey = true) {
    var objArr = [];
    for (var p in obj) {
        var object = {};
        object.value = isNumKey ? Number(p) : p;
        object.label = obj[p];
        objArr.push(object);
    }
    return objArr;
};

/**
 * 检查val是否为空
 * @param {*} val
 * @returns
 */
export const isEmpty = val => {
    if (isNumber(val)) {
        return false;
    }
    return isEmptyFunc(val);
};

/**
 * 检查val是否不为空，0被认为不为空，undefined/null/NaN/{}/[]都会被认为空
 * @param {*} val
 */
export const isNotEmpty = val => {
    if (isNaN(val)) {
        return false;
    }
    if (isNumber(val)) {
        return true;
    }
    return !isEmpty(val);
};

/**
 * 除去对象中空元素
 * @param {*} obj
 * @returns
 */
export const dealObjectEmptyValue = obj => {
    const param = {};
    if (obj === null || obj === undefined || obj === '') return param;
    for (const key in obj) {
        if (obj[key] !== null && obj[key] !== undefined && obj[key] !== '') {
            param[key] = obj[key];
        }
    }
    return param;
};

/**
 * 导出文档
 * @res 数据
 * @name 文件名称
 * @fileType 自定义后缀
 */
export const exportExc = (res, name, fileType) => {
    const blob = new Blob([res.data], {
        type: 'application/msexcel'
    });
    const url = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    let fileName = fileType ? name + '.' + fileType : name + '.xlsx';
    if (res.headers && res.headers['content-disposition']) {
        const contentDisposition = res.headers['content-disposition'] || '';
        const fileNameMatch = contentDisposition.split('filename=');
        if (fileNameMatch.length === 2) {
            const temp = fileNameMatch[1].replace(new RegExp('\\+', 'gm'), '%20');
            fileName = decodeURIComponent(temp);
        }
    }
    link.setAttribute('download', fileName);
    document.body.appendChild(link);
    link.click();
    link.remove();
    window.URL.revokeObjectURL(url);
};

/**
 * 将val值按照format进行格式化
 * @param {*} val
 * @param {*} format
 */
export const format = (val, format = 'YYYY-MM-DD HH:mm') => {
    return dayjs(val).format(format);
};

/**
 * 跳转到统一登录入口
 */
export const logoutUtil = () => {
    const env = import.meta.env.MODE;
    if (env === 'development') {
        location.href = import.meta.env.VITE_LOGIN_PATH + '/login?backUrl=' + location.origin;
    } else {
        location.href = window.apollo.VUE_APP_LOGIN_PATH + '/login?backUrl=' + location.origin;
    }
};

/**
 * 格式化时间
 * @param {时间} time
 * @param {类型} type
 * @param {链接符} join
 */
export const dateFormatFilter = function (time) {
    if (!time) return '';
    const date = new Date(time);
    const y = date.getFullYear();
    let m = date.getMonth() + 1;
    let d = date.getDate();
    let h = date.getHours();
    let min = date.getMinutes();
    let s = date.getSeconds();
    m = m < 10 ? '0' + m : m;
    d = d < 10 ? '0' + d : d;
    h = h < 10 ? '0' + h : h;
    min = min < 10 ? '0' + min : min;
    s = s < 10 ? '0' + s : s;

    return `${y}-${m}-${d} ${h}:${min}`;
};

/**
 * 是否为手机号
 * @param {*} mobile
 * @returns
 */
export const isMobile = mobile => {
    const phone_pattern = new RegExp('^1[3-9][0-9]{9}$', 'i');
    return phone_pattern.test(mobile);
};

/**
 * 密码规则: 至少8-16个字符，由数字或字母组成，不能包含特殊字符。
 * @param {*} password
 * @returns
 */
export const isPassword = password => {
    return /^[A-Za-z0-9\d]{8,16}$/.test(password);
};

/**
 * 大于等于零整数。(不能有0123这样的值)
 * @param {*} number
 * @returns
 */
export const isPositiveInt = number => {
    let flag = typeof number == 'string' && number.length > 1 && number.substr(0, 1) === '0';
    if (flag) {
        return false;
    } else {
        return /^[0-9]+[0-9]*$/.test(number);
    }
};

/**
 * 货币金额(支持正数,保留两位小数)
 * @param {*} number
 * @returns
 */
export const isAmount = number => {
    return /(?:^[1-9]([0-9]+)?(?:\.[0-9]{1,2})?$)|(?:^(?:0){1}$)|(?:^[0-9]\.[0-9](?:[0-9])?$)/.test(number);
};

/**
 * 将科学计数法的数字转为字符串
 * 说明：运算精度丢失方法中处理数字的时候，如果出现科学计数法，就会导致结果出错
 * @param  num
 */
export const toNonExponential = num => {
    if (num == null) {
        return num;
    }
    if (typeof num == 'number') {
        var m = num.toExponential().match(/\d(?:\.(\d*))?e([+-]\d+)/);
        return num.toFixed(Math.max(0, (m[1] || '').length - m[2]));
    } else {
        return num;
    }
};
/**
 * 乘法 - js运算精度丢失问题
 * @param arg1  数1
 * @param arg2  数2
 */
export const floatMultiply = (arg1, arg2) => {
    arg1 = Number(arg1);
    arg2 = Number(arg2);
    if ((!arg1 && arg1 !== 0) || (!arg2 && arg2 !== 0)) {
        return null;
    }
    arg1 = toNonExponential(arg1);
    arg2 = toNonExponential(arg2);
    var n1, n2;
    var r1, r2; // 小数位数
    try {
        r1 = arg1.toString().split('.')[1].length;
    } catch (e) {
        r1 = 0;
    }
    try {
        r2 = arg2.toString().split('.')[1].length;
    } catch (e) {
        r2 = 0;
    }
    n1 = Number(arg1.toString().replace('.', ''));
    n2 = Number(arg2.toString().replace('.', ''));
    return (n1 * n2) / Math.pow(10, r1 + r2);
};

/**
 * 除法 - js运算精度丢失问题
 * @param arg1  数1
 * @param arg2  数2
 */
export const floatDivide = (arg1, arg2) => {
    arg1 = Number(arg1);
    arg2 = Number(arg2);
    if (!arg2) {
        return null;
    }
    if (!arg1 && arg1 !== 0) {
        return null;
    } else if (arg1 === 0) {
        return 0;
    }
    arg1 = toNonExponential(arg1);
    arg2 = toNonExponential(arg2);
    var n1, n2;
    var r1, r2; // 小数位数
    try {
        r1 = arg1.toString().split('.')[1].length;
    } catch (e) {
        r1 = 0;
    }
    try {
        r2 = arg2.toString().split('.')[1].length;
    } catch (e) {
        r2 = 0;
    }
    n1 = Number(arg1.toString().replace('.', ''));
    n2 = Number(arg2.toString().replace('.', ''));
    return floatMultiply(n1 / n2, Math.pow(10, r2 - r1));
    // return (n1 / n2) * Math.pow(10, r2 - r1);   // 直接乘法还是会出现精度问题
};

/**
 * form正则校验
 * @params type
 * number(纯数字)
 * chinese(纯中文)
 * phone(手机号)
 * idcard(一代/二代身份证)
 * email(邮箱)
 * bankcard(银行卡)
 * money(金额)
 */
export const getRegExp = type => {
    const formReg = {
        number: /^\d+$/,
        chinese:
            /^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])+$/,
        phone: /^(?:(?:\+|00)86)?1[3-9]\d{9}$/,
        idcard: /^\d{6}((((((19|20)\d{2})(0[13-9]|1[012])(0[1-9]|[12]\d|30))|(((19|20)\d{2})(0[13578]|1[02])31)|((19|20)\d{2})02(0[1-9]|1\d|2[0-8])|((((19|20)([13579][26]|[2468][048]|0[48]))|(2000))0229))\d{3})|((((\d{2})(0[13-9]|1[012])(0[1-9]|[12]\d|30))|((\d{2})(0[13578]|1[02])31)|((\d{2})02(0[1-9]|1\d|2[0-8]))|(([13579][26]|[2468][048]|0[048])0229))\d{2}))(\d|X|x)$/,
        email: /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
        bankcard: /^[1-9]\d{9,29}$/,
        money: /(?:^[1-9]([0-9]+)?(?:\.[0-9]{1,2})?$)|(?:^(?:0)$)|(?:^[0-9]\.[0-9](?:[0-9])?$)/,
        creditCode: /^(([0-9A-Za-z]{15})|([0-9A-Za-z]{18})|([0-9A-Za-z]{20}))$/
    };
    return formReg[type];
};

/**
 * 生成UUID字符串
 * @returns
 */
export const getUuid = () => {
    var s = [];
    var hexDigits = '0123456789abcdef';
    for (var i = 0; i < 6; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = '4';
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
    s[8] = s[13] = s[18] = s[23];
    var uuid = s.join('');
    return uuid;
};
